#ifndef GLRK_HPP
#define GLRK_HPP

#include <cmath>
#include <iostream>

#include "IRK.hpp"

class GLRK : public IRK {
public:
  GLRK(int dim, double dt, double t0, double t1, int s)
      : IRK(dim, dt, t0, t1) {
    m_s = s;
    if(!initializeSolver()) {
        std::cerr << "Error in GLRK initialization." << std::endl;
        std::exit(EXIT_FAILURE);
    }
        
  }

  bool initializeSolver() {
    m_A.resize(m_s, m_s);
    m_b.resize(m_s);
    m_c.resize(m_s);
    m_A.setZero();
    switch (m_s) {
    case 1: {
      // Set coefficients
      m_c(0) = 0.5;

      // Butcher tableau coefficients
      m_A(0, 0) = 0.5;

      // Weights (b coefficients)
      m_b(0) = 1.0;
      break;
    }
    case 2: {
      // Set coefficients
      const double sqrt3 = std::sqrt(3.0);

      // Butcher tableau coefficients
      m_c(0) = (3.0 - sqrt3) / 6.0;
      m_c(1) = (3.0 + sqrt3) / 6.0;

      m_A(0, 0) = 1.0 / 4.0;
      m_A(0, 1) = (3.0 - 2.0 * sqrt3) / 12.0;
      m_A(1, 0) = (3.0 + 2.0 * sqrt3) / 12.0;
      m_A(1, 1) = 1.0 / 4.0;

      // Weights (b coefficients) - same as last row of A for Gauss methods
      m_b(0) = 0.5;
      m_b(1) = 0.5;
      break;
    }
    case 3: {
      // 定义常数 sqrt15
      const double sqrt15 = std::sqrt(15.0);

      // 设置节点向量 c
      m_c(0) = (5.0 - sqrt15) / 10.0;
      m_c(1) = 0.5;
      m_c(2) = (5.0 + sqrt15) / 10.0;

      // 设置 Butcher 表系数矩阵 A
      m_A(0, 0) = 5.0 / 36.0;
      m_A(0, 1) = 2.0 / 9.0 - sqrt15 / 15.0;
      m_A(0, 2) = 5.0 / 36.0 - sqrt15 / 30.0;

      m_A(1, 0) = 5.0 / 36.0 + sqrt15 / 24.0;
      m_A(1, 1) = 2.0 / 9.0;
      m_A(1, 2) = 5.0 / 36.0 - sqrt15 / 24.0;

      m_A(2, 0) = 5.0 / 36.0 + sqrt15 / 30.0;
      m_A(2, 1) = 2.0 / 9.0 + sqrt15 / 15.0;
      m_A(2, 2) = 5.0 / 36.0;

      // 设置权重向量 b (与 A 矩阵最后一行不同）
      m_b(0) = 5.0 / 18.0;
      m_b(1) = 4.0 / 9.0;
      m_b(2) = 5.0 / 18.0;
      break;
    }
    case 4:
    case 5:
    default:
      std::cerr << "Error: Unsupported s value." << std::endl;
      return false;
    }

    return true;
  }
};

#endif